package top.superflow.engine.runtime

import org.springframework.stereotype.Component
import top.superflow.core.statis.Metrizable
import top.superflow.core.statis.imp.MapStatistics
import top.superflow.core.utils.PojoUtils
import top.superflow.engine.api.{EngineConfig, FlowEngine}
import top.superflow.exception.RequestUnsupportedException
import top.superflow.flow.runtime.flow.{ExtFlow, FlowRequest, FlowResponse}
import top.superflow.flow.runtime.inf.{GeneralRequest, GeneralResponse}
import top.superflow.log.Loggable
import top.superflow.runtime.api.DemandAction

import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.{Future, Promise}

@Component
class DefaultRuntimeFlowEngine extends FlowEngine with Loggable{
 
  /**
   * Related with how the engine is configured
   */
  def initialize(configuration: EngineConfig): Future[Metrizable[_]] = {
    val p = Promise[Metrizable[_]]()
    Future {

      p success MapStatistics.getStatistics(new Object)
    }
    p.future
  }
  
  def reset: Future[Metrizable[_]] = ???
  
  def hotApply(configuration: EngineConfig): Future[Metrizable[_]] = ???
  
  def getConfig : EngineConfig = ???
  
  


  /**
   * Related with how to track the status of the engine
   */
  // Members declared in top.superflow.core.api.Status
  def state[T]: Future[T] = ???
  
  /**
   * Related with how to operate the engine
   */
  def perform[T](demandAction : DemandAction): Future[T] = ???



  def execute(flow: ExtFlow, request: GeneralRequest) : Future[GeneralResponse] = {
    if(flow == null){
      throw new RequestUnsupportedException("The flow itself can't be null")
    }
    val flowRequest = toFlowRequest(request)
    val flowResponse = new FlowResponse

    Future {
      flow.execute(flowRequest, flowResponse)

      flowResponse
    }
  }



  private def toFlowRequest(generalRequest: GeneralRequest) : FlowRequest = {
    val flowRequest = new FlowRequest



    //FlowRequest and GeneralRequest may be different in the future
    PojoUtils.copyTo(generalRequest, flowRequest)

    //only for the test
    flowRequest.addParameter("test", 100000)

    flowRequest
  }
}